﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using AzureGames.Model;

namespace AzureGames.Data.InMemory
{
    public class BoardRepository : IBoardRepository
    {
        static Dictionary<Guid, Model.Board> _boards = new Dictionary<Guid, Model.Board>();
        object _lock = new object();

        public Board GetGameBoard(Guid boardID)
        {
            return _boards[boardID];
        }

        public Board RegisterNewGame(GameDefinition gameDefinition, string playerID, out bool wasJoined)
        {
            lock (_lock)
            {
                // check if there is an existing game that has not been started and is waiting for players
                Board board = _boards.FirstOrDefault(b => b.Value.GameDefinitionID == gameDefinition.ID && b.Value.State == Board.Created).Value;

                if (board == null)
                {
                    wasJoined = false;

                    // create the game
                    board = new Board
                    {
                        GameDefinitionID = gameDefinition.ID,
                        PlayerIDs = new List<string>(),
                        State = Board.Created,
                        Value = 0,
                        Properties = gameDefinition.StartingProperties,
                        ID = Guid.NewGuid(),
                    };

                    _boards.Add(board.ID, board);
                }
                else
                {
                    wasJoined = true;
                    board.LastUpdatedDate = DateTime.Now;
                }

                board.PlayerIDs.Add(playerID);

                if (board.PlayerIDs.Count == gameDefinition.RequiredNumberOfPlayers)
                {
                    board.State = Board.Active;
                }

                return board;
            }
        }

        public void AddGameBoard(Board board)
        {
            lock (_lock)
            {                
                _boards.Add(board.ID, board);
            }            
        }

        public bool UpdateGameBoard(Board board)
        {
            lock (_lock)
            {
                _boards[board.ID].State = board.State;
                _boards[board.ID].Properties = board.Properties;
                _boards[board.ID].LastUpdatedDate = DateTime.Now;
                _boards[board.ID].Value = board.Value;
            }

            return true;
        }

        public List<Board> GetActiveGames(int gameDefinitionID, string playerID)
        {
            return _boards.Values.Where(b => b.GameDefinitionID == gameDefinitionID
                                        && b.PlayerIDs.Any(pID => pID == playerID)
                                        && (b.State == Board.Active || b.State == Board.Created)).ToList();
        }
    }
}
